`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2023/12/08 23:50:51
// Design Name:
// Module Name: test_uart
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////

module test_uart(
  );
  logic clk;
  logic rst;

  logic we_i;
  logic[31:0] addr_i;
  logic[31:0] data_i;

  logic[31:0] data_o;
  logic tx_pin;
  logic rx_pin;

  parameter SYS_FRENCY = 50_000_000;// 时钟 50MHz
  parameter BAUD_FRENCY = 32'h1B8;// 115200 传输一个bit 需要的时钟周期

  localparam UART_CTRL = 8'h0;
  localparam UART_STATUS = 8'h4;
  localparam UART_BAUD = 8'h8;
  localparam UART_TXDATA = 8'hc;
  localparam UART_RXDATA = 8'h10;

  uart uart(
         clk,
         rst,
         we_i,
         addr_i,
         data_i,
         data_o,
         tx_pin,
         rx_pin
       );

  initial
  begin
    clk=1;
    forever
    begin
      #10 clk=~clk;
    end
  end

  initial
  begin
    // 复位
    rst = 0;
    repeat(10) @(posedge clk);
    rst = 1;

    rx_pin = 1; // rx_pin 平常应该为高阻态

    // 使能读写
    we_i = 1;   // 写寄存器使能
    addr_i = UART_CTRL;
    data_i = 32'b11;
    repeat(1) @(posedge clk);
    // 设置rx 为 receiving
    addr_i = UART_STATUS;
    data_i = 2'b00;
    repeat(1) @(posedge clk);
    we_i = 0; // 结束写寄存器
    repeat(1) @(posedge clk);
    // rx_pin 给一个下降沿开始写数据
    rx_pin = 0;
    repeat(BAUD_FRENCY) @(posedge clk);
    // 8 位数据位, uart 先发低位，后发高位
    rx_pin = 1;
    repeat(BAUD_FRENCY) @(posedge clk);
    rx_pin = 0;
    repeat(BAUD_FRENCY) @(posedge clk);
    rx_pin = 1;
    repeat(BAUD_FRENCY) @(posedge clk);
    rx_pin = 0;
    repeat(BAUD_FRENCY) @(posedge clk);
    rx_pin = 1;
    repeat(BAUD_FRENCY) @(posedge clk);
    rx_pin = 1;
    repeat(BAUD_FRENCY) @(posedge clk);
    rx_pin = 0;
    repeat(BAUD_FRENCY) @(posedge clk);
    rx_pin = 0;
    repeat(BAUD_FRENCY) @(posedge clk);
    // 停止位
    rx_pin = 1;
    repeat(BAUD_FRENCY) @(posedge clk);

    addr_i = UART_STATUS;
    repeat(1) @(posedge clk);
    assert(data_o[1] === 1'b1) else
            $error("read status: cannot read");

    addr_i = UART_RXDATA;
    repeat(1) @(posedge clk);
    assert (data_o === 8'b00110101) else
             $error("rx 01010101 failed");

  end

endmodule
